package extend.db.entity.annotation;

import extend.db.entity.Entity;
import extend.db.entity.field.EntityField;
import extend.db.entity.EntityReflectUtil;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 实体元数据
 * <B>说明：</B>
 * <pre>
 *  存储实体注解数据
 * </pre>
 * <B>示例：</B>
 * <pre>
 *  略
 * </pre>
 * <B>日志：</B>
 * <pre>
 *  略
 * </pre>
 * <B>注意事项：</B>
 * <pre>
 *  略
 * </pre>
 */
public class EntityMetadata
{

    private EntityField EntityField;

    /**
     * 目标class
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    private Class clazz;

    /**
     * 对应的表名
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public String tableName;

    /**
     * 实体类属性名称与表字段名称的对应关系
     *<B>说明：</B>
     *<pre>
     *  ["字段名":"属性名"]
     *</pre>
     */
    private Map<String,EntityField> columns = new LinkedHashMap<>();

    /**
     * 表字段名称对应实体属性名称
     *<B>说明：</B>
     *<pre>
     *   ["属性名":"字段名"]
     *</pre>
     */
    private Map<String,EntityField> fields = new LinkedHashMap<>();


    public EntityMetadata(Class clazz)
    {
        this.clazz = clazz;
    }

    /**
     * 解析实体注解
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public void parseAnnotation()
    {
        try {
            // 开始解析注解
            EntityAnnotation.parseAnnotation(this.clazz);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 设置属性名与字段名关系
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public void setRelation(Field field,Map<String,Object> attrs)
    {
        EntityField entityField ;
        String fieldName = field.getName();
        attrs.put(EntityField.FIELD_NAME,fieldName);

        if (!attrs.containsKey(EntityField.VALUE_NAME) || ((String)attrs.get(EntityField.VALUE_NAME)).equals("")) {
            attrs.put(EntityField.COLUMN_NAME,field.getName());
        } else {
            attrs.put(EntityField.COLUMN_NAME,attrs.get(EntityField.VALUE_NAME));
        }

        entityField = EntityField.make(attrs);
        String columnName =  entityField.getColumnName();

        this.columns.put(columnName,entityField);
        this.fields.put(fieldName,entityField);
    }

    public void setTableName(String tableName)
    {
        this.tableName = tableName;
    }

    public String getTableName()
    {
        return this.tableName;
    }

    /**
     * 实体类字段转换成表字段
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Map<String,Object> toColumnValue(Map<String,Object> values)
    {
        EntityField entityField ;

        Map<String,Object> columnsValue = new LinkedHashMap<>();
        for (Map.Entry<String, Object> value : values.entrySet()) {
            if (this.fields.containsKey(value.getKey())) {
                entityField = this.fields.get(value.getKey());
                columnsValue.put(entityField.getColumnName(),entityField.toColumnValue(value.getValue()));
            }
        }

        return columnsValue;
    }

    /**
     * 表字段转换实体类属性
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Map<String,Object> toFieldValue(Map<String,Object> values)
    {
        EntityField entityField ;
        Map<String,Object> columnsValue = new LinkedHashMap<>();

        for (Map.Entry<String, Object> value : values.entrySet()) {
            if (this.columns.containsKey(value.getKey())) {
                entityField = this.columns.get(value.getKey());
                columnsValue.put(entityField.getFieldName(),entityField.toFieldValue(value.getValue()));
            } else {
                columnsValue.put(value.getKey(),value.getValue());
            }
        }

        return columnsValue;
    }

    public Map<String,Object> toAdd(Object target)
    {
        // 读取所有属性
        Map<String,Object> rows = EntityReflectUtil.getAttrs(target);

        return this.toColumnValue(rows);
    }

    /**
     * 从实体抽取更新条件与更新字段
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Map<String,Map<String,Object>> toUpdate(Object target)
    {

        Map<String,Map<String,Object>> condition = new HashMap<>();
        // 读取所有属性
        Map<String,Object> values = EntityReflectUtil.getAttrs(target);
        Map<String,Object> where = new LinkedHashMap<>();
        Map<String,Object> data = new LinkedHashMap<>();
        EntityField entityField;

        for (Map.Entry<String, Object> value : values.entrySet()) {
            if (this.fields.containsKey(value.getKey())) {
                entityField = this.fields.get(value.getKey());
                String columnName = entityField.getColumnName();
                if (entityField.isPk()) {
                    where.put(columnName,entityField.toColumnValue(value.getValue()));
                } else {
                    data.put(columnName,entityField.toColumnValue(value.getValue()));
                }
            }
        }

        condition.put(Entity.WHERE_NAME,where);
        condition.put(Entity.DATA_NAME,data);

        return condition;
    }

    /**
     * 从实体抽取删除where 条件
     *<B>说明：</B>
     *<pre>
     *  查找实体字段的主键作为删除条件
     *</pre>
     */
    public Map<String,Object> toDelete(Object target)
    {
        // 读取所有属性
        Map<String,Object> values = EntityReflectUtil.getAttrs(target);
        Map<String,Object> where = new LinkedHashMap<>();
        EntityField entityField;

        for (Map.Entry<String, Object> value : values.entrySet()) {
            if (this.fields.containsKey(value.getKey())) {
                entityField = this.fields.get(value.getKey());
                String columnName = entityField.getColumnName();
                if (entityField.isPk()) {
                    where.put(columnName,entityField.toColumnValue(value.getValue()));
                }
            }
        }

        return where;
    }

}
